import { log } from "console";

/**
 * @link https://leetcode.cn/problems/valid-sudoku/?envType=study-plan-v2&envId=top-interview-150
 */
function isValidSudoku(board: string[][]): boolean {
  // 判断每一行不存在重复的1-9
  for (let i = 0; i < 9; i++) {
    let dic: string[] = [];
    for (let j = 0; j < 9; j++) {
      if (board[i][j] === ".") continue;
      if (dic.includes(board[i][j])) {
        return false;
      }
      dic.push(board[i][j]);
    }
  }
  // 判断每一列不存在重复的1-9
  for (let i = 0; i < 9; i++) {
    let dic: string[] = [];
    for (let j = 0; j < 9; j++) {
      if (board[j][i] === ".") continue;
      if (dic.includes(board[j][i])) {
        return false;
      }
      dic.push(board[j][i]);
    }
  }
  // 判断3x3中不存在重复的1-9
  for (let i = 0; i < 3; i++) {
    for (let j = 0; j < 3; j++) {
      let dic: string[] = [];
      for (let m = i * 3; m < i * 3 + 3; m++) {
        for (let n = j * 3; n < j * 3 + 3; n++) {
          if (board[m][n] === ".") continue;
          if (dic.includes(board[m][n])) {
            return false;
          }
          dic.push(board[m][n]);
        }
      }
    }
  }
  return true;
}

/**
 * @link https://leetcode.cn/problems/spiral-matrix/?envType=study-plan-v2&envId=top-interview-150
 */
function spiralOrder(matrix: number[][]): number[] {
  // 0 right 1 bottom 2 left 3 top
  let dir = 0;
  let top = 0;
  let left = 0;
  let right = matrix[0].length;
  let bottom = matrix.length;
  let i = 0;
  let j = 0;
  let ans = [matrix[0][0]];
  while (ans.length < matrix[0].length * matrix.length) {
    console.log(i, j, ans);

    if (dir === 0) {
      if (j + 1 < right) {
        j = j + 1;
        ans.push(matrix[i][j]);
      } else {
        dir = dir + 1;
        top = top + 1;
      }
    } else if (dir === 1) {
      if (i + 1 < bottom) {
        i = i + 1;
        ans.push(matrix[i][j]);
      } else {
        dir = dir + 1;
        right = right - 1;
      }
    } else if (dir === 2) {
      if (j - 1 >= left) {
        j = j - 1;
        ans.push(matrix[i][j]);
      } else {
        dir = dir + 1;
        bottom = bottom - 1;
      }
    } else {
      if (i - 1 >= top) {
        i = i - 1;
        ans.push(matrix[i][j]);
      } else {
        dir = 0;
        left = left + 1;
      }
    }
  }
  console.log(ans);

  return ans;
}

/**
 * @link https://leetcode.cn/problems/rotate-image/?envType=study-plan-v2&envId=top-interview-150
 */
/**
 Do not return anything, modify matrix in-place instead.
 */
function rotate(matrix: number[][]): void {
  let ans = [];
  for (let i = 0; i < matrix.length; i++) {
    let tmp = [];
    for (let j = matrix.length - 1; j >= 0; j--) {
      tmp.push(matrix[j][i]);
    }
    ans.push(tmp);
  }
  for (let i = 0; i < ans.length; i++) {
    for (let j = 0; j < ans.length; j++) {
      matrix[i][j] = ans[i][j];
    }
  }
}

/**
 * @link https://leetcode.cn/problems/set-matrix-zeroes/?envType=study-plan-v2&envId=top-interview-150
 */
/**
 Do not return anything, modify matrix in-place instead.
 */
function setZeroes(matrix: number[][]): void {
  let st: [number, number][] = [];
  for (let i = 0; i < matrix.length; i++) {
    for (let j = 0; j < matrix[0].length; j++) {
      if (matrix[i][j] === 0) {
        st.push([i, j]);
      }
    }
  }
  console.log([...st]);

  const setZero = (t: [number, number]) => {
    let tmpx = t[0];

    while (tmpx - 1 >= 0) {
      matrix[tmpx - 1][t[1]] = 0;
      tmpx = tmpx - 1;
    }
    tmpx = t[0];
    while (tmpx + 1 < matrix.length) {
      matrix[tmpx + 1][t[1]] = 0;
      tmpx = tmpx + 1;
    }
    let tmpy = t[1];
    while (tmpy - 1 >= 0) {
      matrix[t[0]][tmpy - 1] = 0;
      tmpy = tmpy - 1;
    }
    tmpy = t[1];
    while (tmpy + 1 < matrix[0].length) {
      matrix[t[0]][tmpy + 1] = 0;
      tmpy = tmpy + 1;
    }
  };
  while (st.length) {
    let target = st.shift();
    console.log(target);

    if (target) setZero(target);
  }
  console.log(matrix);
}

/**
 * @link https://leetcode.cn/problems/game-of-life/?envType=study-plan-v2&envId=top-interview-150
 */
/**
 Do not return anything, modify board in-place instead.
 */
function gameOfLife(board: number[][]): void {
  let ans: number[][] = [];
  for (let i = 0; i < board.length; i++) {
    ans[i] = new Array();
    for (let j = 0; j < board[0].length; j++) {
      ans[i][j] = 0;
    }
  }
  const getInfo = (x: number, y: number) => {
    let res = [0, 0];
    if (x - 1 >= 0 && y - 1 >= 0) {
      if (board[x - 1][y - 1] === 0) res[0] += 1;
      else res[1] += 1;
    }
    if (x - 1 >= 0) {
      if (board[x - 1][y] === 0) res[0] += 1;
      else res[1] += 1;
    }
    if (x - 1 >= 0 && y + 1 < board[0].length) {
      if (board[x - 1][y + 1] === 0) res[0] += 1;
      else res[1] += 1;
    }
    if (y - 1 >= 0) {
      if (board[x][y - 1] === 0) res[0] += 1;
      else res[1] += 1;
    }
    if (y + 1 < board[0].length) {
      if (board[x][y + 1] === 0) res[0] += 1;
      else res[1] += 1;
    }
    if (x + 1 < board.length && y - 1 >= 0) {
      if (board[x + 1][y - 1] === 0) res[0] += 1;
      else res[1] += 1;
    }
    if (x + 1 < board.length && y + 1 < board[0].length) {
      if (board[x + 1][y + 1] === 0) res[0] += 1;
      else res[1] += 1;
    }
    if (x + 1 < board.length) {
      if (board[x + 1][y] === 0) res[0] += 1;
      else res[1] += 1;
    }
    return res;
  };
  const handle = (x: number, y: number) => {
    let [dead, alive] = getInfo(x, y);
    console.log(x, y, getInfo(x, y));

    if (board[x][y] === 0) {
      // 判断是否有正好三个1
      if (alive === 3) {
        return 1;
      }
      return 0;
    } else {
      if (alive === 2 || alive === 3) {
        return 1;
      }
      return 0;
    }
  };
  for (let i = 0; i < board.length; i++) {
    for (let j = 0; j < board[0].length; j++) {
      let tmp = handle(i, j);
      ans[i][j] = tmp;
    }
  }
  for (let i = 0; i < board.length; i++) {
    for (let j = 0; j < board[0].length; j++) {
      board[i][j] = ans[i][j];
    }
  }
}

export default { isValidSudoku, spiralOrder, rotate, setZeroes, gameOfLife };
